<template>
  <el-dialog v-model="visible" :title="title" width="80%" top="5vh">
    <!-- Loading 遮罩 -->
    <div v-if="loading" class="flex justify-center items-center h-full">
      <el-icon><Loading /></el-icon>
      <span class="ml-2">文件加载中，请耐心等待...</span>
    </div>

    <!-- 图片预览 -->
    <div v-if="type === 'image'" class="flex justify-center">
      <el-image
        :src="url"
        :preview-src-list="[url]"
        fit="contain"
        style="max-height:80vh;"
      />
    </div>

    <!-- PDF 预览 -->
    <div v-else-if="type === 'pdf'" id="pdf" style="height:80vh; overflow:auto;"></div>

    <!-- Word 预览 -->
    <div v-else-if="type === 'word'" id="docx" style="height:80vh; overflow:auto;"></div>

    <!-- Excel 预览 -->
    <div v-else-if="type === 'excel'" id="excel" style="height:80vh; overflow:auto;"></div>

    <!-- 其它文件 -->
    <template #footer>
      <div class="flex justify-end items-center">
        <el-button type="primary" @click="downloadFile">下载文件</el-button>
        <el-button @click="visible = false">关闭</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, watch, nextTick } from "vue";
import { ElMessage } from "element-plus";

// 预览库
import jsPreviewDocx from "@js-preview/docx";
import "@js-preview/docx/lib/index.css";

import jsPreviewExcel from "@js-preview/excel";
import "@js-preview/excel/lib/index.css";

import jsPreviewPdf from "@js-preview/pdf";

const props = defineProps({
  modelValue: { type: Boolean, default: false },
  url: { type: String, default: "" }, // 文件 URL 或 blob URL
  rawFile: { type: Object, default: null }, // 可选 File 对象
  title: { type: String, default: "文件预览" },
  type: { type: String, default: "" } // image/pdf/word/excel
});

const emit = defineEmits(["update:modelValue"]);
const visible = ref(props.modelValue);
const loading = ref(false);

// 最大文件大小
const MAX_FILE_SIZE = 70 * 1024 * 1024; // 70MB

watch(() => props.modelValue, val => visible.value = val);
watch(visible, val => emit("update:modelValue", val));

// 单例预览器
let docxViewer: any = null;
let excelViewer: any = null;
let pdfViewer: any = null;

watch([visible, () => props.type, () => props.url], async ([val]) => {
  if (!val) return;
  await nextTick();

  try {
    const rawFile = props.rawFile instanceof File ? props.rawFile : null;

    if (rawFile && rawFile.size > MAX_FILE_SIZE) {
      console.log("⚠️ 文件过大，无法预览", rawFile.size);
      ElMessage.warning("文件过大，暂不支持在线预览，请下载查看");
      return;
    }

    console.log("⏳ 开始加载文件预览", props.title, props.type, props.url);
    loading.value = true;

    // 获取 source
    let source: ArrayBuffer | string = props.url;
    if (props.url.startsWith("blob:") && rawFile) {
      source = await rawFile.arrayBuffer();
    } else if (!props.url.startsWith("blob:")) {
      try {
        const resp = await fetch(props.url);
        if (!resp.ok) throw new Error(`请求失败: ${resp.status}`);
        source = await resp.arrayBuffer();
      } catch (err) {
        console.error("❌ 获取服务端文件失败", err);
        ElMessage.error("文件加载失败，请下载查看");
        return;
      }
    }

    await nextTick(); // 确保 DOM 渲染完成

    if (props.type === "word") {
      const container = document.getElementById("docx");
      if (!container) throw new Error("Word 容器未渲染完成");
      container.innerHTML = "";
      docxViewer = jsPreviewDocx.init(container); // 每次重新 init
      console.log("📄 调用 Word 预览");
      await docxViewer.preview(source);
      console.log("✅ Word 预览完成");

    } else if (props.type === "excel") {
      const container = document.getElementById("excel");
      if (!container) throw new Error("Excel 容器未渲染完成");
      container.innerHTML = "";
      excelViewer = jsPreviewExcel.init(container);
      console.log("📊 调用 Excel 预览");
      await excelViewer.preview(source);
      console.log("✅ Excel 预览完成");

    } else if (props.type === "pdf") {
      const container = document.getElementById("pdf");
      if (!container) throw new Error("PDF 容器未渲染完成");
      container.innerHTML = "";
      pdfViewer = jsPreviewPdf.init(container);
      console.log("📑 调用 PDF 预览");
      await pdfViewer.preview(source);
      console.log("✅ PDF 预览完成");
    }

  } catch (err) {
    console.error("❌ 文件预览失败：", err);
    ElMessage.error("文件预览失败，请下载查看");
  } finally {
    loading.value = false;
    console.log("⏹ 文件加载结束");
  }
});

// 下载文件
const downloadFile = () => {
  const link = document.createElement("a");
  link.href = props.url;
  link.download = props.url.split("/").pop() || "file";
  link.click();
};
</script>
